/*
 * ServerDaemon.h
 *
 *  Created on: Mar 18, 2012
 *      Author: Victor Nidens victornlj@gmail.com
 * 		Author:	Mikhail S. Ananyevskiy, PhD, msaipme@yandex.ru
 *
 *	This file is part of Cloud Mechatronic Laboratory (CMLab) software.
 *
 *	Cloud Mechatronic Laboratory (CMLab) for CMLab is free software: you can redistribute it and/or modify
 *	it under the terms of the GNU Lesser General Public License as published by
 *	the Free Software Foundation, either version 3 of the License, or
 *	(at your option) any later version.
 *
 *	Cloud Mechatronic Laboratory (CMLab) software is distributed in the hope that it will be useful,
 *	but WITHOUT ANY WARRANTY; without even the implied warranty of
 *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *	GNU Lesser General Public License for more details.
 *
 *	You should have received a copy of the GNU Lesser General Public License
 *	along with Cloud Mechatronic Laboratory (CMLab). If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef SERVERDAEMON_H_
#define SERVERDAEMON_H_

#include <fstream>
#include <netinet/in.h>
#include "protocol/protocol.h"
#include <tr1/unordered_map>
#include <tr1/unordered_set>
#include <vector>
#include <mysql/mysql.h>

#define HashMap std::tr1::unordered_map
#define HashSet	std::tr1::unordered_set

using namespace std;

typedef struct {
	string	name;
	uint8	ip[4];
	int		tcpPort;
	int		udpPort;
	int		regulatorPort;
	bool	savePacketStat;
	string	dbHost;
	int		dbPort;
	string	dbUser;
	string	dbUserPassword;
	string	dbName;
	string	dbTable;
} ServerConfig;

class ServerDaemon {

protected:

	ServerConfig config;

	ofstream log;
	struct sockaddr_in serverTcpSocket;							//main TCP server socket (client)
	struct sockaddr_in serverUdpSocket;							//main UDP server socket (client)
	struct sockaddr_in serverRegulatorSocket;					//main TCP server socket (regulator)
	int serverTcpSocketFD;										//file descriptor for TCP server socket (client)
	int serverUdpSocketFD;										//file descriptor for UPD server socket (client)
	int serverRegulatorSocketFD	;								//file descriptor for TCP server socket (regulator)

	HashMap<string, int> connectedTcpClients;					//map of connected TCP clients' names and corresponding file descriptors
	HashMap<string, struct sockaddr_in> connectedUdpClients;	//map of connected UPD clients' names and corresponding network addresses
	HashMap<string, int> connectedRegulators;					//map of connected regulators' names and corresponding file descriptors

	HashSet<int> openedTcpSocketsFD;							//set of file descriptors for opened clients' connections
	HashSet<int> openedRegulatorsSocketsFD;						//set of file descriptors for opened regulators' connections

	vector<ExchangePacket> regulatorsRequestQueue;
	vector<ExchangePacket> clientsPacketsQueue;
	vector<ExchangePacket> awaitingClientResponse;

	HashMap<string, string> availableNXTDevices;

	MYSQL *dbConnection;

	/**
	 * Bind sockets for clients and regulators access
	 *
	 * @return 		0 	- if all sockets were binded successfully
	 * 				-1	- if any socket can't be binded
	 */
	int bindSockets();

	void daemonize();
	void mainloop();
	void commit();

	void handleRegulatorsRequests();
	void handleClientsRequests();

	int initDBStorage();
	void savePacketStat(ExchangePacket *packet);

	static void sighandler(int signum);

public:
	ServerDaemon(ServerConfig conf);

	/**
	 * Start the server daemon and run its main loop
	 */
	void exec();

};

#endif /* SERVERDAEMON_H_ */
